/*
 * Part of knowledge engineering (ke) course work, 2010/11
 */
package se.bth.ke.firstfriend.web;

import java.util.List;
import se.bth.ke.firstfriend.model.Article;
import de.nixis.commons.web.base.model.UserBase;
import de.nixis.commons.web.base.Controller;
import se.bth.ke.firstfriend.dto.ToggleTodoPriorityDTO;
import se.bth.ke.firstfriend.model.CheckPoint;
import se.bth.ke.firstfriend.model.dto.TodoInfo;
import java.text.ParseException;
import java.util.Date;
import se.bth.ke.firstfriend.util.Util;
import javax.ws.rs.Produces;
import javax.annotation.security.RolesAllowed;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import se.bth.ke.firstfriend.model.CompletedCheckPoint;
import se.bth.ke.firstfriend.model.Todo;
import se.bth.ke.firstfriend.dto.TodoView;
import static se.bth.ke.firstfriend.util.Util.PRODUCES_HTML;

/**
 *
 * @author markus, nico
 */
@Component
@Path("/todo")
public class TodoController extends Controller {
    
    @PersistenceContext
    private EntityManager em;

    @GET
    @Path("/{id:[\\d+]}/togglePriority")
    @Produces(PRODUCES_HTML)
    @Transactional
    public Object togglePriority(
            @PathParam("id") long todoId) {

        Todo todo = getTodoById(todoId, getActiveUser());

        int oldPriority = todo.getPriority();
        todo.setPriority((oldPriority + 1) % 3);
        
        return new ToggleTodoPriorityDTO(oldPriority, todo);
    }

    @GET
    @Path("/{id:[\\d+]}/changeDeadline")
    @Produces(PRODUCES_HTML)
    public Todo changeDeadline(@PathParam("id") long todoId) {
        return getTodoById(todoId, getActiveUser());
    }
    
    @POST
    @Path("/{id:[\\d+]}/deadline")
    @Produces(PRODUCES_HTML)
    @Transactional
    public Todo changeDeadlineSave(
            @PathParam("id") long todoId,
            @FormParam("deadline") String deadline) {

        Todo todo = getTodoById(todoId, getActiveUser());
        Date date = null;

        try {
            date = Util.parseDate(deadline);
        } catch (ParseException e) {
            throw new WebApplicationException(e, Status.BAD_REQUEST);
        }

        todo.setDeadline(date);
        return todo;
    }

    @GET
    @Path("/{id:[\\d+]}/toggleComplete")
    @Transactional
    @Produces(PRODUCES_HTML)
    public TodoInfo toggleComplete(@PathParam("id") long todoId) {

        TodoInfo info = (TodoInfo) em.createNamedQuery("Todo.getTodoInfoByIdAndUser")
                                     .setParameter("user", getActiveUser())
                                     .setParameter("id", todoId)
                                     .getSingleResult();

        System.out.println(info);
        
        info.changeTodoStateTo(info.isDone() ?
            CheckPoint.State.WORK_IN_PROGRESS :
            CheckPoint.State.DONE);
        
        return info;
    }
    
    @GET
    @Path("/{id:[\\d+]}/toggleRemove")
    @Transactional
    @Produces(PRODUCES_HTML)
    public TodoInfo toggleRemove(@PathParam("id") long todoId) {

        TodoInfo info = (TodoInfo) em.createNamedQuery("Todo.getTodoInfoByIdAndUser")
                                     .setParameter("user", getActiveUser())
                                     .setParameter("id", todoId)
                                     .getSingleResult();

        info.changeTodoStateTo(info.isDeleted() ? 
            CheckPoint.State.WORK_IN_PROGRESS :
            CheckPoint.State.DELETED);

        return info;
    }

    @POST
    @Path("/{id:[\\d+]}/finalComment")
    public Todo addCompletedNotes(
            @PathParam("id") long todoId,
            @FormParam("timeInvested") int timeInvested,
            @FormParam("comment") String comment) {
            
        Todo todo = getTodoById(todoId, getActiveUser());
        CompletedCheckPoint done = (CompletedCheckPoint) em.createQuery("SELECT c FROM CompletedCheckPoint c WHERE c.todo = :todo ORDER BY c.createdAt DESC")
                .setParameter("todo", todo)
                .setMaxResults(1)
                .getSingleResult();

        done.setComment(comment);
        done.setTimeInvested(timeInvested);
        
        return todo;
    }
    
    @GET
    @RolesAllowed("user")
    @Transactional
    public TodoView list(
            @QueryParam("invert") @DefaultValue("false") boolean sortOrderInverted,
            @QueryParam("order") @DefaultValue("deadline") String orderBy,
            @QueryParam("show") @DefaultValue("todo") String showBy,
            @QueryParam("page") @DefaultValue("0") int page) {

        try {
            return new TodoView(getActiveUser(), em, orderBy, showBy, sortOrderInverted, page);
        } catch (IllegalArgumentException e) {
            throw new WebApplicationException(e, Status.BAD_REQUEST);
        } catch (IllegalStateException e) {
            throw new WebApplicationException(e, Status.FORBIDDEN);
        }
    }

    @GET
    @RolesAllowed("user")
    @Produces("application/json")
    @Path("/timeline")
    public Object getTimelineData(
            @QueryParam("invert") @DefaultValue("false") boolean sortOrderInverted,
            @QueryParam("order") @DefaultValue("deadline") String orderBy,
            @QueryParam("show") @DefaultValue("todo") String showBy,
            @QueryParam("page") @DefaultValue("0") int page) {

        try {
            TodoView todos = new TodoView(getActiveUser(), em, orderBy, showBy, sortOrderInverted, page);
            // return new TimelineData(todos.getViewableItems());
            return null;
        } catch (IllegalArgumentException e) {
            throw new WebApplicationException(e, Status.BAD_REQUEST);
        } catch (IllegalStateException e) {
            throw new WebApplicationException(e, Status.FORBIDDEN);
        }
    }

    private Todo getTodoById(long todoId, UserBase user) {
        return (Todo) em.createQuery("SELECT t FROM Todo t WHERE t.id = :id and t.user = :user")
                        .setParameter("id", todoId)
                        .setParameter("user", user)
                        .getSingleResult();
    }
}
